package com.cocotingo.snail.examples;

import java.awt.Color;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;

import javax.swing.JFrame;

import com.cocotingo.snail.Animation;
import com.cocotingo.snail.Image;
import com.cocotingo.snail.MouseEvent;
import com.cocotingo.snail.PaintMode;
import com.cocotingo.snail.View;
import com.cocotingo.snail.ViewContext;
import com.cocotingo.snail.ViewGraphics;
import com.cocotingo.snail.template.EventHandler;
import com.cocotingo.snail.template.TemplateLoader;
import com.cocotingo.snail.template.TemplateView;
import com.cocotingo.snail.template.annotations.Handler;
import com.cocotingo.snail.template.annotations.Outlet;
import com.cocotingo.snail.util.Vector2D;

public class Example02 {

	public static void main(String[] args) {
		
		// standard Swing
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setSize(800, 600);
		frame.setVisible(true);
		
		// load XML file
		TemplateLoader loader = new TemplateLoader(frame.getGraphicsConfiguration());
		try {
			loader.load("Example02.xml", Example02.class);
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}
		
		// bridge to Snail GUI
		ViewContext context = new ViewContext(frame.getContentPane());
		context.setRootView(loader.makeView("ExampleView")); // instantiate view from XML file
		
	}
	
	// XML-based views must subclass from TemplateView
	public static class ExampleView extends TemplateView {
		
		@Outlet public TemplateView logoView = null; // outlet variable. automatically initialized by XML
		
		@Override
		protected void createdFromTemplate(final TemplateLoader loader) {
			// outlet vars are loaded.
			// you can proceed additional initialization here.
			
			// define the REPAINT behavior for logoView:
			logoView.addEventHandler(REPAINT, new EventHandler() {
				@Override
				public void handle(TemplateView sender, String eventName, Object arg) {
					ViewGraphics g = (ViewGraphics) arg;
					Image logo = loader.getResourceAsImage("logo"); // load a image via XML loader
					g.drawImage(logo, 0, 0, sender.getWidth(), sender.getHeight());
				}
			});
		}
		
		@Handler
		public void button1Clicked(View sender, MouseEvent e) {
			// create a rectangle
			final View rect = new View();
			rect.setBackgroundColor(Color.cyan); // default bg-color is white.
			rect.setPosition(150, 100);
			rect.setSize(100, 100);
			rect.setPaintMode(PaintMode.DIRECTLY); // simple rectangle. no need to buffer it.
			this.addSubview(rect);
			
			// create animation
			Animation animation = new Animation(5.0f, Animation.EaseInEaseOut) {
				
				@Override
				protected void animate(float progress) {
					AffineTransform transform = new AffineTransform();
					transform.rotate(progress * 2 * Math.PI, 45, 45);
					transform.scale(1 + progress, 1 + progress);
					rect.setTransform(transform);
					rect.setAlpha(1 - progress);
				}
				
				@Override
				protected void completed(boolean canceled) {
					rect.removeFromSuperView();
				}
				
			};
			animation.commit(); // commit to play
			
			e.handle();
		}
		
		// dragging code:
		
		private Vector2D v0;
		
		@Handler
		public void ballPressed(View sender, MouseEvent e) {
			v0 = e.getPosition(sender); // remember relative location
			e.handle();
		}
		
		@Handler
		public void ballDragged(View sender, MouseEvent e) {
			sender.setPosition(Vector2D.subtract(e.getPosition(sender.getSuperView()), v0));
			e.handle();
		}
		
		@Handler
		public void ballReleased(View sender, MouseEvent e) {
			e.handle();
		}
		
	}
	
	/**
	 * A simple button.
	 */
	public static class ExampleButton extends TemplateView {
		
		private String text = "";
		private boolean pressed = false;
		
		// customized property can be also used in XML file.
		public String getText() {
			return text;
		}
		
		public void setText(String text) {
			this.text = text;
			setNeedsRepaint();
		}
		
		@Handler
		public void repaintButton(View sender, ViewGraphics g) {
			g.setColor(pressed ? Color.red : Color.black);
			
			// draw border
			g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);
			
			// draw label at center of the button, AWT things.
			TextLayout layout = new TextLayout(text, g.getFont(), g.getFontRenderContext());
			float x = (getWidth() - layout.getAdvance()) / 2;
			float y = (getHeight() + layout.getAscent() - layout.getDescent()) / 2;
			layout.draw(g, x, y);
		}
		
		@Handler
		public void buttonMousePressed(View sender, MouseEvent e) {
			pressed = true;
			setNeedsRepaint();
			e.handle();
		}
		
		@Handler
		public void buttonMouseReleased(View sender, MouseEvent e) {
			pressed = false;
			setNeedsRepaint();
			e.handle();
		}
		
	}

	/**
	 * A simple ball.
	 */
	public static class Ball extends TemplateView {
		
		private final Ellipse2D.Float shape = new Ellipse2D.Float(); // AWT-based shape model
		
		public Ball() {
			
			addEventHandler(SIZE_CHANGED, new EventHandler() {
				@Override
				public void handle(TemplateView sender, String eventName, Object arg) {
					shape.width = getWidth();
					shape.height = getHeight();
					setNeedsRepaint();
				}
			});
			
			addEventHandler(REPAINT, new EventHandler() {
				@Override
				public void handle(TemplateView sender, String eventName, Object arg) {
					ViewGraphics g = (ViewGraphics) arg;
					g.setColor(Color.blue);
					g.fill(shape);
				}
			});
		}
		
		@Override
		public boolean isInside(Vector2D point) {
			return shape.contains(point.toPoint2D());
		}
		
	}
}
